<template>
  <div class="render-target-prc">
    <!-- threejs官网的 ‘一些有用的链接’ -->
    <!-- 螺旋圆圈 -->
    <div class="canvas" ref="canvas"></div>
  </div>
</template>

<script lang="ts">
import { Vue, Options } from 'vue-property-decorator';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const scene = new THREE.Scene();
scene.background = new THREE.Color('black');
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10);
camera.position.z = 3;
{
  const light = new THREE.DirectionalLight(0xffffff, 2);
  light.position.set(-1, 2, 4);
  scene.add(light);
}
{
  const light = new THREE.DirectionalLight(0xffffff, 2);
  light.position.set(2, -2, 3);
  scene.add(light);
}
const renderer = new THREE.WebGLRenderer({
  alpha: true,
  antialias: true,
});
renderer.debug.checkShaderErrors = false;
renderer.setClearColor(new THREE.Color(), 0);
renderer.setPixelRatio(750 / window.innerWidth);
const longHelper = new THREE.Object3D();
const latHelper = new THREE.Object3D();
const pointHelper = new THREE.Object3D();
longHelper.add(latHelper);
latHelper.add(pointHelper);
pointHelper.position.z = 1;
const temp = new THREE.Vector3();
@Options({ components: {} })
export default class SpiralCircle extends Vue {
  public rect: DOMRect|null = null;

  public resizeRendererToDisplaySize(renderer: THREE.WebGLRenderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needSize = canvas.width !== width || canvas.height !== height;
    if (needSize) {
      renderer.setSize(width, height, false);
    }
    return needSize;
  }
  public makeInstance(geometry: THREE.BufferGeometry, color: number, x: number) {
    const material = new THREE.MeshPhongMaterial({
      color,
      side: THREE.DoubleSide,
      shadowSide: 100,
    });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    cube.position.x = x;
    return cube;
  }
  public getPoint(lat: number, long: number) {
    latHelper.rotation.x = lat;
    longHelper.rotation.y = long;
    longHelper.updateMatrixWorld(true);
    return pointHelper.getWorldPosition(temp).toArray();
  }
  public makeSpherePositions(segmentsAround: number, segmentDown: number) {
    // *6？？
    const numVertices = segmentsAround * segmentDown * 6;
    const numComponents = 3;
    const positions = new Float32Array(numVertices * numComponents);
    const indices = [];

    let posNdx = 0;
    let ndx = 0;
    for (let down = 0; down < segmentDown; down++) {
      const v0 = down / segmentDown;
      const v1 = (down + 1) / segmentDown;
      const lat0 = (v0 - .5) * Math.PI;
      const lat1 = (v1 - .5) * Math.PI;
      for (let across = 0; across < segmentsAround; across++) {
        const u0 = across / segmentsAround;
        const u1 = (across + 1) / segmentsAround;
        const long0 = u0 * Math.PI * 2;
        const long1 = u1 * Math.PI * 2;

        positions.set(this.getPoint(lat0, long0), posNdx);
        posNdx += numComponents;
        positions.set(this.getPoint(lat1, long0), posNdx);
        posNdx += numComponents;
        positions.set(this.getPoint(lat0, long1), posNdx);
        posNdx += numComponents;
        positions.set(this.getPoint(lat1, long1), posNdx);
        posNdx += numComponents;

        // 0，1，2   2，1，3
        indices.push(ndx, ndx + 1, ndx + 2, ndx + 2, ndx + 1, ndx + 3);
        ndx += 4;
      }
    }
    return { positions, indices };
  }
  public mounted() {
    this.rect = (this.$el as HTMLElement).getBoundingClientRect();
    renderer.setSize(this.rect.width, this.rect.height, false);
    (this.$refs.canvas as HTMLDivElement).append(renderer.domElement);

    const segmentsAround =  24;// 纬度
    const segmentDown = 16; // 经度
    const { positions, indices } = this.makeSpherePositions(segmentsAround, segmentDown);
    const normals = positions.slice();

    const geometry = new THREE.BufferGeometry();
    const positionNumComponents = 3;
    const normalNumComponents = 3;
    const positionAttribute = new THREE.BufferAttribute(positions, positionNumComponents);
    // ？？？？
    positionAttribute.setUsage(THREE.DynamicDrawUsage);
    geometry.setAttribute('position', positionAttribute);
    geometry.setAttribute('normal', new THREE.BufferAttribute(normals, normalNumComponents));
    // setIndex 设置缓存的index
    geometry.setIndex(indices);

    const cubes = [
      this.makeInstance(geometry, 0xff0000, 0),
    ];

    renderer.setAnimationLoop((time) => {
      // eslint-disable-next-line no-param-reassign
      // time *= 0.001;

      // if (this.resizeRendererToDisplaySize(renderer)) {
      //   const canvas  = renderer.domElement;
      //   camera.aspect = canvas.clientWidth / canvas.clientHeight;
      //   camera.updateProjectionMatrix();
      // }

      // for (let i = 0; i < positions.length; i++) {
      //   const quad = (i / 12 | 0);
      //   const ringId = quad / segmentsAround | 0;
      //   const ringQuadId = quad % segmentsAround;
      //   const ringU = ringQuadId / segmentsAround;
      //   const angle = ringU * Math.PI * 2;

      //   temp.fromArray(normals, i);
      //   temp.multiplyScalar(THREE.MathUtils.lerp(1, 1.4, Math.sin(time + ringId + angle) * .5 + .5));
      //   temp.toArray(positions, i);
      // }
      // positionAttribute.needsUpdate = true;

      // cubes.forEach((cube, index) => {
      //   const speed = -.2 + index * .1;
      //   const rot = time * speed;
      //   cube.rotation.y = rot;
      // });

      renderer.render(scene, camera);
    });

    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableZoom = false;
  }
}
</script>

<style lang="postcss" scoped>
  .render-target-prc{
    touch-action: none;
    position: absolute;
    left: 0;top: 0;
    width: 100%;height: 100%;
    background: #98bbd1;
    .canvas{
      position: absolute;
      left: 0;top: 0;
      width: 100%;height: 100%;
       :deep(canvas){
        width: 100%;height: 100%;
      }
    }
  }
</style>
